home *** CD-ROM | disk | FTP | other *** search
-
- Patrick O'Lone suggests the following idea which sounds interesting to
- add as an optional mode of Cache_Lite class.
- (still not tested in the Cache_Lite context)
-
- -------------------------------------------------------------------------
- If you use the flags:
-
- ignore_user_abort(true);
-
- $fd = dio_open($szFilename, O_CREATE | O_EXCL | O_TRUNC | O_WRONLY,
- 0644);
- if (is_resource($fd)) {
-
- dio_fcntl($fd, F_SETLKW, array('type' => F_WRLCK));
- dio_write($fd, $szBuffer);
- dio_fcntl($fd, F_SETLK, array('type' => F_UNLCK));
- dio_close($fd);
-
- }
-
- ignore_user_abort(false);
-
- Only the first process will attempt to create a file. Additional
- processes will see that a file already exists (at the system level), and
- will fail. Another thing to note is that the file descriptor must be
- opened using dio_open(), and certain features, like fgets() won't work
- with it. If your just doing a raw write, dio_write() should be just
- fine. The dio_read() function should be used like:
-
- $fd = dio_open($szFilename, O_RDONLY|O_NONBLOCK, 0644);
- if (is_resource($fd)) {
-
- dio_fcntl($fd, F_SETLKW, array('type' => F_RDLCK));
- $szBuffer = dio_read($fd, filesize($szFilename));
- dio_fcntl($fd, F_SETLK, array('type' => F_UNLCK));
- dio_close($fd);
-
- }
-
- You still use locking to ensure that a write process can finish before
- another attempts to read the file. We also set non-blocking mode in read
- mode so that multiple readers can access the same resource at the same
- time. NOTE: Direct I/O support must be compiled into PHP for these
- features to work (--enable-dio).
- -------------------------------------------------------------------------
-
-
-
- Another optionnal mode could be (Mike Benoit's interesting idea) :
- (not tested)
-
- -------------------------------------------------------------------------
- However recently I ran in to a problem with it and one of the projects
- I'm working on (http://phpgacl.sourceforge.net/). phpGACL caches _many_
- ( on the order of 10,000-100,000) very small pieces of data, when I
- tried using Cache Lite for this, my file system didn't like it much
- since there were so many files in a single directory.
-
- So I patched Cache Lite to support a hashed directory structure. ie:
-
- <root cache dir>/<group>/<number between 0-999>/<chopped CRC32>
-
- ../default
- ../default/081
- ../default/081/081162803
- ../default/215
- ../default/215/215106191
- ../default/333
- ../default/333/33376174
- ../default/366
- ../default/366/366703566
- ../default/500
-
- I ran a few rough benchmarks, and this method was slower until the cache
- file numbers started growing to over 30,000 or so. Another advantage to
- doing it this way is it's really easy to clear the cache for a specific
- group. :)
-
- The other change I made was to make it so cache data that was read from
- the file system was also stored in memory for subsequent reads. Scripts
- that actually do this should see quite a large increase in performance,
- if the script doesn't actually hit a cache entry more then once, it
- obviously slows things down slightly and uses more memory. Currently it
- ignores cache expire times when it stores data in memory, but in theory
- this shouldn't be a big deal.
-
- <?
- /*
- * phpGACL - Generic Access Control List - Hashed Directory Caching.
- * Copyright (c) 2002-2003 Mike Benoit
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For questions, help, comments, discussion, etc., please join the
- * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
- *
- * You may contact the author of phpGACL by e-mail at:
- * ipso@snappymail.ca
- *
- * The latest version of phpGACL can be obtained from:
- * http://phpgacl.sourceforge.net/
- *
- */
- require_once("Cache_Lite.php");
-
- define('DIR_SEP', DIRECTORY_SEPARATOR);
-
- class Hashed_Cache_Lite extends Cache_Lite
- {
- /**
- * Memory caching variable
- *
- * @var array $_memoryCache
- */
- var $_memoryCache = NULL;
-
- /**
- * Test if a cache is available and (if yes) return it - Original version by Fabien MARTY <fab@php.net>
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @return string data of the cache (or false if no cache available)
- * @access public
- */
- function get($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- $this->_id = $id;
- $this->_group = $group;
-
- if ($this->_caching) {
- if ($this->_memoryCache[$group.'-'.$id]) {
- return ($this->_memoryCache[$group.'-'.$id]);
- } else {
- $this->_setFileName($id, $group);
- if ($doNotTestCacheValidity) {
- if (file_exists($this->_file)) {
- $this->_memoryCache[$group.'-'.$id] = $this->_read();
- return ( ($this->_memoryCache[$group.'-'.$id]) );
- }
- } else {
- if (@filemtime($this->_file) > $this->_refreshTime) {
- $this->_memoryCache[$group.'-'.$id] = $this->_read();
- return ( ($this->_memoryCache[$group.'-'.$id]) );
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Make a file name (with path)
- *
- * @param string $id cache id
- * @param string $group name of the group
- * @access private
- */
- function _setFileName($id, $group)
- {
- //CRC32 with SUBSTR is still faster then MD5.
- $encoded_id = substr(crc32($id),1);
- //$encoded_id = md5($id);
-
- //Generate just the directory, so it can be created.
- //Groups will have there own top level directory, for quick/easy purging of an entire group.
- $dir = $this->_cacheDir.$group.'/'.substr($encoded_id,0,3);
- $this->_create_dir_structure($dir);
-
- $this->_file = $dir.'/'.$encoded_id;
- }
-
- /**
- * Create full directory structure, Ripped straight from the Smarty Template engine.
- * Version: 2.3.0
- * Copyright: 2001,2002 ispi of Lincoln, Inc.
- *
- * @param string $dir Full directory.
- * @access private
- */
- function _create_dir_structure($dir)
- {
- if (!@file_exists($dir)) {
- $dir_parts = preg_split('!\\'.DIR_SEP.'+!', $dir, -1, PREG_SPLIT_NO_EMPTY);
- $new_dir = ($dir{0} == DIR_SEP) ? DIR_SEP : '';
- foreach ($dir_parts as $dir_part) {
- $new_dir .= $dir_part;
- if (!file_exists($new_dir) && !mkdir($new_dir, 0771)) {
- Cache_Lite::raiseError('Cache_Lite : problem creating directory \"$dir\" !', -3);
- return false;
- }
- $new_dir .= DIR_SEP;
- }
- }
- }
- }
-
- ?>
- -------------------------------------------------------------------------
-